'''
@summary: Generates python\cal\ws_consts.py according to Wireshark's source.
'''
# generate_ws_consts.py
#
# Pyreshark Plugin for Wireshark. (https://github.com/ashdnazg/pyreshark)
#
# Copyright (c) 2013 by Eshed Shaham.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

import sys
import os.path

COMMENT_CHAR = "#"
CAPTION_WIDTH = 40

HEADER = """'''
@summary: Auto Generated by generate_ws_consts.py. Sets all the required constants from Wireshark.
'''

"""

ENUM_FILE_NAME = 0
ENUM_NAME = 1
ENUM_CAPTION = 2
ENUMS = [(os.path.join("..","..","epan","ftypes","ftypes.h"), "ftenum", "FIELD TYPES"),
         (os.path.join("..","..","epan","proto.h"), "base_display_e", "DISPLAY VALUES"), # until 1.10
         (os.path.join("..","..","epan","proto.h"), "field_display_e", "DISPLAY VALUES"), # since 1.12 
         (os.path.join("..","..","epan","time_fmt.h"), "absolute_time_display_e", "DISPLAY VALUES (TIME)"),
         (os.path.join("..","..","epan","column_info.h"), "", "COLUMN IDS"),
         (os.path.join("..","..","epan","column-utils.h"), "", "COLUMN IDS"),]

         
DEFINE = "#define"
DEFINE_FILE_NAME = 0
DEFINE_PREFIX = 1
DEFINE_CAPTION = 2

DEFINES = [(os.path.join("..","..","epan","proto.h"), "enc_", "ENCODINGS"),
           (os.path.join("..","..","epan","proto.h"), "base_", "DISPLAY VALUES (MORE)"),
           (os.path.join("..","..","epan","proto.h"), "pi_", "EXPERT INFO")]

MACRO_FILE_NAME = 0
MACRO_NAME = 1
MACRO_CAPTION = 2

MACROS = [(os.path.join("..","..","epan","proto.h"), "hfill", "HEADER FILL MACRO")]

MISC_CAPTION = "MISC"
MISC = """
if "ENC_ASCII" in dir():
    ENC_TEXT_DEFAULT = ENC_ASCII
elif "ENC_UTF8" in dir():
    ENC_TEXT_DEFAULT = ENC_UTF8
else:
    ENC_TEXT_DEFAULT = ENC_NA


DATA = "data"
REMAINING_LENGTH = -1
"""

def get_enum(file_name, enum_name):
    all_values = []
    count = 0
    in_file = open(file_name, "rb")
    
    found = False
    line = in_file.readline()
    while True:
        while line != "" and not "enum" in line:
            line = in_file.readline()
        
        if line == "":
            break
        
        if enum_name in line:
            found = True
            
        line = line = in_file.readline()
        while "}" not in line:
            entry = line.split("/")[0].split(",")[0].strip()
            if entry != "":
                if "=" in entry:
                    (name, current_value) = entry.split("=")
                    try:
                        count = int(current_value)
                    except:
                        pass
                else:
                    name = entry
                    current_value = count
                    
                all_values.append((name, str(current_value)))
                count += 1
            line = in_file.readline()
        
        if found or enum_name in line:
            break
        else:
            all_values = []
    
    in_file.close()
    return all_values

def fix_macro(s):
    values = s.replace(" ", "").split(",")
    fixed_values = []
    for value in values:
        try:
            v = int(value)
        except ValueError:
            if value == "NULL":
                v = None
            else:
                v = 0
        fixed_values.append(v)
    return tuple(fixed_values)
    
def get_define(file_name, define_prefix, is_macro = False):
    all_values = []
    in_file = open(file_name, "rb")
    
    line = in_file.readline()
    while line != "":
        if (line.strip().lower().startswith(DEFINE) and line.strip().lower().replace(DEFINE,"").strip().startswith(define_prefix) and
                (not is_macro or line.strip().lower().replace(DEFINE,"").strip()[len(define_prefix)].strip() == "")):
            entry = line.split("/")[0].strip()[len(DEFINE):].strip().replace("\t", " ")
            space_position = entry.index(" ")
            name, value = entry[:space_position].strip(), entry[space_position:].strip()
            all_values.append((name, value))
        line = in_file.readline()
    
    return all_values
    
    
def main(argv):
    out_file = open(argv[1], "wb")
    out_file.write(HEADER)
    for enum in ENUMS:
        if os.path.exists(enum[ENUM_FILE_NAME]):
            entries = get_enum(enum[ENUM_FILE_NAME], enum[ENUM_NAME])
            if len(entries) > 0:
                out_file.write("%s\n" % ((" %s " % (enum[ENUM_CAPTION],)).center(CAPTION_WIDTH, COMMENT_CHAR),))
                for name, value in entries:
                    out_file.write("%s = %s\n" % (name, value))
                out_file.write("\n")
    
    for define in DEFINES:
        if os.path.exists(define[DEFINE_FILE_NAME]):
            entries = get_define(define[DEFINE_FILE_NAME], define[DEFINE_PREFIX])
            if len(entries) > 0:
                out_file.write("%s\n" % ((" %s " % (define[DEFINE_CAPTION],)).center(CAPTION_WIDTH, COMMENT_CHAR),))
                for name, value in entries:
                    out_file.write("%s = %s\n" % (name, value))
                out_file.write("\n")
    
    for macro in MACROS:
        if os.path.exists(macro[MACRO_FILE_NAME]):
            entries = get_define(macro[MACRO_FILE_NAME], macro[MACRO_NAME], True)
            if len(entries) > 0:
                name, value = entries[0]
                value = fix_macro(value)
                out_file.write("%s\n" % ((" %s " % (macro[MACRO_CAPTION],)).center(CAPTION_WIDTH, COMMENT_CHAR),))
                out_file.write("%s = %s\n" % (name, value))
                out_file.write("\n")
        
    out_file.write("%s\n%s" % ((" %s " % (MISC_CAPTION,)).center(CAPTION_WIDTH, COMMENT_CHAR), MISC))
    out_file.close()

if '__main__' == __name__:
    if len(sys.argv) < 2:
        print "Usage: %s <out_file>" % (sys.argv[0],)
        exit(1)
    main(sys.argv)
